﻿using AVCUMPlatform.HelperLibrary.Cache;
using AVCUMPlatform.HelperLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AVCUMPlatform.Entities;

namespace AVCUMPlatform.MiniWXService.Model
{
    /// <summary>
    /// 微信小程序token 
    /// </summary>
    public class MiniWXToken
    {
        /// <summary>
        /// 单例
        /// </summary>
        private static MiniWXToken instance = new MiniWXToken();
        /// <summary>
        /// 锁
        /// </summary>
        private object sync_obj = new object();
        /// <summary>
        /// 微信应用id
        /// </summary>
        private string _appId { get; set; }
        /// <summary>
        /// 微信密钥
        /// </summary>
        private string _appSecret { get; set; }
        /// <summary>
        /// 缓存键
        /// </summary>
        private string cacheKey_Token = "MiniWxCacheToken";
        /// <summary>
        /// 缓存实例
        /// </summary>
        ICache cache = CacheFactory.GetCacheInstance();
        /// <summary>
        /// 缓存模型
        /// </summary>
        private CacheEntity cacheWxEntity = null;

        /// <summary>
        /// 获取单例
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="appsecret"></param>
        /// <returns></returns>
        public static MiniWXToken GetInstance(string appid, string appsecret)
        {
            instance._appId = appid;
            instance._appSecret = appsecret;
            return instance;
        }

        /// <summary>
        /// token
        /// </summary>
        public string AccessToken
        {
            get
            {
                lock (sync_obj)
                {
                    DoGetToken();
                }
                return cacheWxEntity.Content;
            }
        }

        /// <summary>
        /// 获取token 方法
        /// </summary>
        private void DoGetToken()
        {
            if (cache.IsExists(cacheKey_Token + _appId))
            {
                cacheWxEntity = cache.Get<CacheEntity>(cacheKey_Token + _appId);
            }
            else
            {
                cacheWxEntity = new CacheEntity() { ElapsedAt = DateTime.Now, UpdateTime = DateTime.Now };
            }

            if (DateTime.Now >= cacheWxEntity.ElapsedAt)
            {
                var token = HTTPHelper.Post<MiniWXTokenEntity>(
                    string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",
                    _appId,
                    _appSecret),
                    string.Empty);
                if (token.Expires_in > 0)
                {
                    int expireSeconds = token.Expires_in - 300;
                    cacheWxEntity.Content = token.Access_token;
                    cacheWxEntity.ElapsedAt = DateTime.Now.AddSeconds(expireSeconds);
                    cacheWxEntity.UpdateTime = DateTime.Now;
                    cache.Remove(cacheKey_Token + _appId);
                    cache.Set(cacheKey_Token + _appId, cacheWxEntity, TimeSpan.FromSeconds(expireSeconds));
                }
            }
        }

        /// <summary>
        /// 清除旧的token
        /// </summary>
        public string RefreshToken()
        {
            if (cache.IsExists(cacheKey_Token + _appId))
            {
                cache.Remove(cacheKey_Token + _appId);
            }
            var token = HTTPHelper.Post<MiniWXTokenEntity>(
                    string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",
                    _appId,
                    _appSecret),
                    string.Empty);
            if (token.Expires_in > 0)
            {
                int expireSeconds = token.Expires_in - 300;
                cacheWxEntity.Content = token.Access_token;
                cacheWxEntity.ElapsedAt = DateTime.Now.AddSeconds(expireSeconds);
                cacheWxEntity.UpdateTime = DateTime.Now;
                cache.Remove(cacheKey_Token + _appId);
                cache.Set(cacheKey_Token + _appId, cacheWxEntity, TimeSpan.FromSeconds(expireSeconds));
            }
            return cacheWxEntity.Content;
        }
    }
}
